/// <reference path="../types.ts" />
/// <reference path="../helpers.ts" />
/// <reference path="organization.ts" />

module $Xrm.Messages {
    export class RetrieveEntityRequest extends OrganizationRequest {
        public EntityFilters: string = null;
        public MetadataId: string = "00000000-0000-0000-0000-000000000000";
        public RetrieveAsIfPublished: bool = true;
        public LogicalName: string = null;

        constructor() {
            super("RetrieveEntity");
        }

        GetResponse(responseXml: Document): RetrieveEntityResponse {
            return new RetrieveEntityResponse(responseXml);
        }

        ToSoapXml(): string {
            this.Parameters["EntityFilters"] = this.EntityFilters;
            this.Parameters["MetadataId"] = this.MetadataId;
            this.Parameters["RetrieveAsIfPublished"] = this.RetrieveAsIfPublished;
            this.Parameters["LogicalName"] = this.LogicalName;

            return super.ToSoapXml();
        }
    }

    export class RetrieveEntityResponse extends OrganizationResponse {
        public EntityMetadata: EntityMetadata;

        constructor(responseXml?: Document) {
            super("RetrieveEntity", responseXml);

            this.ParseResponse(responseXml);
            this.BindProperties();
        }

        BindProperties(): void {
            super.BindProperties();

            this.EntityMetadata = this.Results["EntityMetadata"];
        }

        ParseResponse(responseXml: Document): void {
            this.Results = []; // clear the values parsed from the base class

            var rn = _xml.getChildNode(responseXml.firstChild.firstChild.firstChild.firstChild, 'a:Results');
            if (rn != null && rn.firstChild != null) {
                var entities = rn.firstChild; // KeyValuePairOfstringanyType
                if (entities != null && entities.childNodes.length > 1) {
                    var keyvalues = entities.childNodes;

                    var key = _xml.getText(keyvalues[0]);
                    var value = keyvalues[1];

                    var metadata = new $Xrm.EntityMetadata();

                    this.ParseNested(value, metadata);

                    this.Results[key] = metadata;
                }
            }
        }

        private ParseNested(node: any, metadataField: any): void {
            if (node.childNodes != null && node.childNodes != undefined && node.childNodes.length > 1) {
                for (var i = 0; i < node.childNodes.length; i++) {
                    var current = node.childNodes[i];
                    var nodeName = _xml.stripNamespace(current.nodeName);

                    // these guys get special treatment :)
                    if (nodeName == "AttributeMetadata") {
                        nodeName = _xml.getText(_xml.getChildNode(current, "c:LogicalName"));
                    }
                    else if (nodeName == "ManyToManyRelationshipMetadata"
                        || nodeName == "ManyToOneRelationshipMetadata"
                        || nodeName == "OneToManyRelationshipMetadata") {
                        nodeName = _xml.getText(_xml.getChildNode(current, "c:SchemaName"));
                    }
                    else if (nodeName == "Privileges") {
                        nodeName = _xml.getText(_xml.getChildNode(current, "c:Name"));
                    }

                    if (nodeName != null) {
                        metadataField[nodeName] = new Object();
                        if (current.childNodes != null && current.childNodes != undefined && current.childNodes.length > 1) {
                            this.ParseNested(current, metadataField[nodeName]);
                        }
                        else {
                            metadataField[nodeName] = _xml.getValue(current);
                        }
                    }
                }
            }
            else {
                var nodeName = _xml.stripNamespace(node.nodeName);
                metadataField[nodeName] = _xml.getValue(node);
            }
        }
    }
}